package com.myk.game.gobangchess.rooms;

import com.myk.game.gobangchess.constants.BoardStyleData;
import com.myk.game.gobangchess.constants.ColorCost;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.signs.*;
import com.myk.game.gobangchess.utils.GridsUtils;
import com.myk.game.gobangchess.Room;

import java.util.ArrayList;
import java.util.List;

/**
 * 震棋
 */
public class ShockRoom extends Room {

    private int[] lastPoint;

    private List<int[]> thePrePoint = new ArrayList<>();
    private List<int[]> theNowPoint = new ArrayList<>();

    public ShockRoom(String roomName) {
        super(roomName, "\t\t计中计saiwei设计的棋，原本棋子击退后三连即可获胜，江柯和夏日研究后发现落子四连立即获胜更有趣。", "震棋", roomName.contains("十路") ? BoardStyleData.getGoBangStyle(10, 10) : BoardStyleData.getGoBangStyle(8, 8), true, true);
    }

    @Override
    public String getRuleText() {
        return "双方轮流落子，落子后会击退周围一圈所有棋子1格，如果击退到的格子已经有棋子了则不能击退，可将棋子击退出棋盘外移除掉。  落子后或者击退棋子后棋子形成四连立刻获胜。";
    }

    @Override
    public void resetGrids() {
        super.resetGrids();
        lastPoint = null;
        thePrePoint = new ArrayList<>();
        theNowPoint = new ArrayList<>();
    }

    @Override
    public void doRule(int row, int col, int value) {
        if (curGrids[row][col] == 0) { //只能落在空位置
            stepAdd();
            curGrids[row][col] = value; //实际落子
            lastPoint = new int[]{row, col, value};
            WinState winState = checkWin();
            if (winState != null) {
                addHistory(cur == 1 ? "黑方落在" : "白方落在" + (row + 1) + "行" + (col + 1) + "列"); //添加战报记录
                doOver(winState.winMode, winState.winMsg);
            }
            else {
                ShockPiece();
                WinState winState2 = checkWin();
                if (winState2 != null) {
                    addHistory(cur == 1 ? "黑方落在" : "白方落在" + (row + 1) + "行" + (col + 1) + "列"); //添加战报记录
                    doOver(winState2.winMode, winState2.winMsg);
                }
                else {
                    addHistory(cur == 1 ? "黑方落在" : "白方落在" + (row + 1) + "行" + (col + 1) + "列"); //添加战报记录
                    noticeChangeMove();
                }
            }
        }
    }

    private void ShockPiece() {
        /*
        int[][] moves = {
                {-1, -1}, {-1, 0}, {-1, 1},
                { 0, -1},          { 0, 1},
                { 1, -1}, { 1, 0}, { 1, 1}
        };
         */
        int[][] moves = {
                {-1, -1}, {-1, 0}, {-1, 1},
                {0, -1}, {0, 1},
                {1, -1}, {1, 0}, {1, 1}
        };
        for (int[] move : moves) {
            int nextRow = lastPoint[0] + move[0];
            int nextCol = lastPoint[1] + move[1];
            if (nextRow < curGrids.length && nextCol < curGrids[0].length && nextRow >= 0 && nextCol >= 0) {
                if (curGrids[nextRow][nextCol] != 0) {
                    int value = curGrids[nextRow][nextCol];
                    int moreNextRow = nextRow + move[0];
                    int moreNextCol = nextCol + move[1];
                    if (moreNextRow < 0 || moreNextRow >= curGrids.length || moreNextCol < 0 || moreNextCol >= curGrids[0].length) {
                        curGrids[nextRow][nextCol] = 0;
                        thePrePoint.add(new int[]{nextRow, nextCol});
                        theNowPoint.add(new int[]{moreNextRow, moreNextCol, value});
                    }
                    else if (curGrids[moreNextRow][moreNextCol] == 0) {
                        curGrids[moreNextRow][moreNextCol] = value;
                        curGrids[nextRow][nextCol] = 0;
                        thePrePoint.add(new int[]{nextRow, nextCol});
                        theNowPoint.add(new int[]{moreNextRow, moreNextCol});
                    }
                }
            }
        }
    }

    @Override
    public String getGameInfo() {
        signList.clear();
        if (lastPoint != null) {
            signList.add(new AroundSign(getIndex(lastPoint[0], lastPoint[1]), "#00000000", "#FF00FF00", 1.0f));
        }
        if (!thePrePoint.isEmpty()) {
            int size = thePrePoint.size();
            for (int i = 0; i < size; i++) {
                int[] prePoint = thePrePoint.get(i);
                int[] nowPoint = theNowPoint.get(i);
                if (nowPoint[0] < 0 || nowPoint[0] >= curGrids.length || nowPoint[1] < 0 || nowPoint[1] >= curGrids[0].length) {
                    addArrowSignalShort(prePoint[0], prePoint[1], nowPoint[0], nowPoint[1], nowPoint[2]);
                }
                else {
                    addArrowSignal(prePoint[0], prePoint[1], nowPoint[0], nowPoint[1]);
                }
            }
        }
        return super.getGameInfo();
    }

    public void addArrowSignal(int startRow, int startCol, int endRow, int endCol) {
        signList.add(new LineSign(getIndex(startRow, startCol), getIndex(endRow, endCol), ColorCost.MOVE_ARROW, 1));
    }

    public void addArrowSignalShort(int startRow, int startCol, int endRow, int endCol, int endValue) {
        if (startRow > endRow && startCol > endCol) {
            signList.add(new BadgeSign(getIndex(startRow, startCol), "↖", 0, ColorCost.MOVE_ARROW, endValue == 2 ? ColorCost.DETAINED_BADGE_BLACK : ColorCost.DETAINED_BADGE_WHITE));
        }
        else if (startRow > endRow && startCol < endCol) {
            signList.add(new BadgeSign(getIndex(startRow, startCol), "↗", 2, ColorCost.MOVE_ARROW, endValue == 2 ? ColorCost.DETAINED_BADGE_BLACK : ColorCost.DETAINED_BADGE_WHITE));
        }
        else if (startRow < endRow && startCol > endCol) {
            signList.add(new BadgeSign(getIndex(startRow, startCol), "↙", 6, ColorCost.MOVE_ARROW, endValue == 2 ? ColorCost.DETAINED_BADGE_BLACK : ColorCost.DETAINED_BADGE_WHITE));
        }
        else if (startRow < endRow && startCol < endCol) {
            signList.add(new BadgeSign(getIndex(startRow, startCol), "↘", 8, ColorCost.MOVE_ARROW, endValue == 2 ? ColorCost.DETAINED_BADGE_BLACK : ColorCost.DETAINED_BADGE_WHITE));
        }
        else if (startRow == endRow && startCol > endCol) {
            signList.add(new BadgeSign(getIndex(startRow, startCol), "←", 3, ColorCost.MOVE_ARROW, endValue == 2 ? ColorCost.DETAINED_BADGE_BLACK : ColorCost.DETAINED_BADGE_WHITE));
        }
        else if (startRow == endRow && startCol < endCol) {
            signList.add(new BadgeSign(getIndex(startRow, startCol), "→", 5, ColorCost.MOVE_ARROW, endValue == 2 ? ColorCost.DETAINED_BADGE_BLACK : ColorCost.DETAINED_BADGE_WHITE));
        }
        else if (startRow > endRow) {
            signList.add(new BadgeSign(getIndex(startRow, startCol), "↑", 1, ColorCost.MOVE_ARROW, endValue == 2 ? ColorCost.DETAINED_BADGE_BLACK : ColorCost.DETAINED_BADGE_WHITE));
        }
        else if (startRow < endRow) {
            signList.add(new BadgeSign(getIndex(startRow, startCol), "↓", 7, ColorCost.MOVE_ARROW, endValue == 2 ? ColorCost.DETAINED_BADGE_BLACK : ColorCost.DETAINED_BADGE_WHITE));
        }
    }

    private void noticeChangeMove() {
        if (cur == 1) {
            noticeWhiteMove();
        }
        else if (cur == 2) {
            noticeBlackMove();
        }
        thePrePoint = new ArrayList<>();
        theNowPoint = new ArrayList<>();
    }

    //获取成5的次数
    protected WinState checkWin() {
        int lengthB = checkFormation(1, 4);
        int lengthW = checkFormation(2, 4);
        boolean isBW = lengthB > 0;
        boolean isWW = lengthW > 0;
        boolean gridFull = GridsUtils.getDataCount(curGrids, 0) == 0;
        int winValue = 0;
        if (cur == 1 ? isBW : isWW) {
            winValue = cur;
        }
        else if (cur == 1 ? isWW : isBW) {
            winValue = cur == 1 ? 2 : 1;
        }
        if (winValue == 1) {
            return new WinState(WinMode.BLACK_WIN, player_black.getNickNameOrTemp() + "执黑棋战胜" + player_white.getNickNameOrTemp());
        }
        else if (winValue == 2) {
            return new WinState(WinMode.WHITE_WIN, player_white.getNickNameOrTemp() + "执白棋战胜" + player_black.getNickNameOrTemp());
        }
        else if (gridFull) {
            return new WinState(WinMode.BOTH_DRAW, player_black.getNickNameOrTemp() + "-黑棋战平" + player_white.getNickNameOrTemp() + "-白棋");
        }
        else {
            return null;
        }
    }


    private int checkFormation(int value, int winLength) {
        int rows = curGrids.length;
        int cols = curGrids[0].length;
        int formationCount = 0;

        // 水平方向
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols - winLength + 1; j++) {
                int length = 0;
                for (int k = j; k < j + winLength; k++) {
                    if (curGrids[i][k] == value) {
                        length++;
                    }
                    else {
                        break;
                    }
                }
                if (length >= winLength) {
                    formationCount += (length - winLength + 1);
                }
            }
        }

        // 垂直方向
        for (int i = 0; i < rows - winLength + 1; i++) {
            for (int j = 0; j < cols; j++) {
                int length = 0;
                for (int k = i; k < i + winLength; k++) {
                    if (curGrids[k][j] == value) {
                        length++;
                    }
                    else {
                        break;
                    }
                }
                if (length >= winLength) {
                    formationCount += (length - winLength + 1);
                }
            }
        }

        // 左上到右下方向
        for (int i = 0; i < rows - winLength + 1; i++) {
            for (int j = 0; j < cols - winLength + 1; j++) {
                int length = 0;
                for (int k = 0; k < winLength; k++) {
                    if (curGrids[i + k][j + k] == value) {
                        length++;
                    }
                    else {
                        break;
                    }
                }
                if (length >= winLength) {
                    formationCount += (length - winLength + 1);
                }
            }
        }

        // 右上到左下方向
        for (int i = 0; i < rows - winLength + 1; i++) {
            for (int j = winLength - 1; j < cols; j++) {
                int length = 0;
                for (int k = 0; k < winLength; k++) {
                    if (curGrids[i + k][j - k] == value) {
                        length++;
                    }
                    else {
                        break;
                    }
                }
                if (length >= winLength) {
                    formationCount += (length - winLength + 1);
                }
            }
        }

        return formationCount;
    }

    public static class WinState {
        public int winMode;
        public String winMsg;

        public WinState(int winMode, String winMsg) {
            this.winMode = winMode;
            this.winMsg = winMsg;
        }

    }

}
